
package no.ffi.tpm;

import iaik.tc.tss.api.structs.common.TcBlobData;
import iaik.tc.tss.api.structs.tpm.TcTpmPcrInfoShort;
import no.ffi.tpm.crypto.CryptoOperations;

/**
 * This object decode the TPM_CERTIFY_INFO structure, and allows to extract
 * the digest of the certified key and the nonce used.
 * 
 * @author Federico Mancini 06/12/2012
 */
public class DecodeTPMCertInfo {

    //Self-explaining variables
    private byte[] TPM_CERTIFY_INFO; // The TPM_CERTIFY_INFO structure
    //All the info contained in it
    private byte[] version_;
    private int keyUsage_;
    private long keyFlags_;
    private short authDataUsage_;
    private long algorithmID;
    private int encScheme;
    private int sigScheme;
    private long parmSize;
    private byte[] algorithmParms_;
    private byte[] pubKeyDigest_;
    private byte[] nonce_;
    private boolean parentPcrStatus_;
    private long pcrInfoSize;
    private byte[] pcrInfo_;
    private int keyDigIndex;
    private int nonceIndex;
    /**
     * Constructor that decodes the byte array containing the 
     *  TPM_CERTIFY_INFO structure created by the TPM
     * */
    public DecodeTPMCertInfo(byte[] tpmCertifyInfo) {

        TPM_CERTIFY_INFO = tpmCertifyInfo;
        //First 4 bytes, TPM version (major and minor, and revision version)
        version_ = TPMUtils.getRange(tpmCertifyInfo, 0, 4);
        //2 bytes The type of the key being certified
        keyUsage_ = TPMUtils.decodeUINT16(TPMUtils.byteArrayToShortArray(TPMUtils.getRange(tpmCertifyInfo, 4, 2)));
        //4 bytes The flags associated with the certified key
        keyFlags_ = TPMUtils.decodeUINT32(TPMUtils.byteArrayToShortArray(TPMUtils.getRange(tpmCertifyInfo, 6, 4)));
        //1 byte boolean flag, whether the key password is needed for key usage in TPM
        authDataUsage_ = TPMUtils.getRange(tpmCertifyInfo, 10, 1)[0];
        //4 bytes Algorithm information (RSA)
        algorithmID = TPMUtils.decodeUINT32(TPMUtils.byteArrayToShortArray(TPMUtils.getRange(tpmCertifyInfo, 11, 4)));
        //2 bytes The encryption scheme type
        encScheme = TPMUtils.decodeUINT16(TPMUtils.byteArrayToShortArray(TPMUtils.getRange(tpmCertifyInfo, 15, 2)));
        //2 bytes The signature scheme used
        sigScheme = TPMUtils.decodeUINT16(TPMUtils.byteArrayToShortArray(TPMUtils.getRange(tpmCertifyInfo, 17, 2)));
        // 4 bytes Length of the algorithm parameters
        parmSize = TPMUtils.decodeUINT32(TPMUtils.byteArrayToShortArray(TPMUtils.getRange(tpmCertifyInfo, 19, 4)));
        // parmSize byte The algorithm parameters
        algorithmParms_ = TPMUtils.getRange(tpmCertifyInfo, 23, (int) parmSize);
        //20 bytes The digest of the certified key modulus
        keyDigIndex=23+ (int) parmSize;
        pubKeyDigest_ = TPMUtils.getRange(tpmCertifyInfo, keyDigIndex, 20);
        nonceIndex=19 + 4 + (int) parmSize + 20;
        //20 bytes The nonce 
        nonce_ = TPMUtils.getRange(tpmCertifyInfo,nonceIndex , 20);
        //1 byte boolean flag, are pcs used
        parentPcrStatus_ = TPMUtils.byteToBoolean(TPMUtils.getRange(tpmCertifyInfo, 63 + (int) parmSize, 1)[0]);
        //4 bytes How many PCR values are associated to the key
        pcrInfoSize = TPMUtils.decodeUINT32(TPMUtils.byteArrayToShortArray(TPMUtils.getRange(tpmCertifyInfo, 64 + (int) parmSize, 4)));
        //pcrInfoSize bytes The PCR values associated to the key
        pcrInfo_ = TPMUtils.getRange(tpmCertifyInfo, 64 + (int) parmSize + 4, (int) pcrInfoSize);//decodeBytes(pcrInfoSize);
        //TcTpmPcrInfoShort pcrs=new TcTpmPcrInfoShort(TcBlobData.newByteArray(pcrInfo_));
     
        System.out.println("keyUsage: " + keyUsage_ + "\n" + "keyflags: " + keyFlags_ + "\n" + "algID: " + algorithmID + "\n" + "encScheme: " + encScheme + "\n sigScheme: " + sigScheme + "\n paramSize: " + parmSize);
        System.out.println("AlgParams: "+CryptoOperations.toHexString(algorithmParms_));
        System.out.println("PubKeyDigest: "+CryptoOperations.toHexString(pubKeyDigest_));
        System.out.println("Nonce: "+CryptoOperations.toHexString(nonce_));
        System.out.println("parentPcrstatus: "+  (parentPcrStatus_));
        System.out.println("PcrInfoSize: "+ (pcrInfoSize));
        System.out.println("PcrInfo: "+CryptoOperations.toHexString(pcrInfo_));
    }

  

    /**
     * @return the TPM_CERTIFY_INFO
     */
    public byte[] getTPM_CERTIFY_INFO() {
        return TPM_CERTIFY_INFO;
    }

    /**
     * @return the version_
     */
    public byte[] getVersion() {
        return version_;
    }

    /**
     * @return the keyUsage_
     */
    public int getKeyUsage() {
        return keyUsage_;
    }

    /**
     * @return the keyFlags_
     */
    public long getKeyFlags() {
        return keyFlags_;
    }

    /**
     * @return the authDataUsage_
     */
    public short getAuthDataUsage() {
        return authDataUsage_;
    }

    /**
     * @return the algorithmID
     */
    public long getAlgorithmID() {
        return algorithmID;
    }

    /**
     * @return the encScheme
     */
    public int getEncScheme() {
        return encScheme;
    }

    /**
     * @return the sigScheme
     */
    public int getSigScheme() {
        return sigScheme;
    }

    /**
     * @return the parmSize
     */
    public long getParmSize() {
        return parmSize;
    }

    /**
     * @return the algorithmParms_
     */
    public byte[] getAlgorithmParms() {
        return algorithmParms_;
    }

    /**
     * @return the pubKeyDigest_
     */
    public byte[] getPubKeyDigest() {
        return pubKeyDigest_;
    }

    /**
     * @return the nonce_
     */
    public byte[] getNonce() {
        return nonce_;
    }

    /**
     * @return the parentPcrStatus_
     */
    public boolean getParentPcrStatus() {
        return parentPcrStatus_;
    }

    /**
     * @return the pcrInfoSize
     */
    public long getPcrInfoSize() {
        return pcrInfoSize;
    }

    /**
     * @return the pcrInfo_
     */
    public byte[] getPcrInfo() {
        return pcrInfo_;
    }

    /**
     * @return the keyDigIndex
     */
    public int getKeyDigIndex() {
        return keyDigIndex;
    }

    /**
     * @return the nonceIndex
     */
    public int getNonceIndex() {
        return nonceIndex;
    }
}
